home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
translate
/
trstring.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-14
|
8KB
|
402 lines
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "internal.h"
#include "../misc/misc.h"
PUBLIC LANG_STRING::LANG_STRING (char _lang, const char *_str)
{
lang = _lang;
str.setfrom (_str);
}
PUBLIC LANG_STRING *LANG_STRINGS::getitem(int no)
{
return (LANG_STRING*)ARRAY::getitem(no);
}
PUBLIC TR_STRING::TR_STRING(const char *_id)
{
changed = 0;
id.setfrom (_id);
}
/*
Return the ID of the translation unit
*/
PUBLIC const char *TR_STRING::getid()
{
return id.get();
}
/*
Indicate if this translation unit has been modified (by msgscan).
This implied that the ID is still in use.
*/
PUBLIC int TR_STRING::was_changed ()
{
return changed;
}
PUBLIC void TR_STRING::reset_changed ()
{
changed = 0;
rstmodified();
}
/*
Return how many translation are available for this translation unit.
An obsolete message may have 0 translations.
*/
PUBLIC int TR_STRING::getnblang()
{
return tb.getnb();
}
/*
Add a comment line to the TR_STRING definition.
*/
PUBLIC void TR_STRING::add2comment(const char *_comment)
{
comment.append (_comment);
}
/*
Add a new translation for this message
*/
PUBLIC SSTRING *TR_STRING::settranslation (char lang, const char *str)
{
changed = 1;
setmodified();
LANG_STRING *ta = gettranslation (lang);
if (ta == NULL){
ta = new LANG_STRING (lang,str);
tb.add (ta);
}else{
ta->str.setfrom (str);
}
return &ta->str;
}
/*
Get the message for a given language
Return NULL if not available.
*/
PUBLIC LANG_STRING *TR_STRING::gettranslation (char lang)
{
LANG_STRING *ret = NULL;
int n = tb.getnb();
for (int i=0; i<n; i++){
LANG_STRING *t = tb.getitem(i);
if (t->lang == lang){
ret = t;
break;
}
}
return ret;
}
/*
Remove one translation.
*/
PUBLIC void TR_STRING::deltranslation (char lang)
{
int n = tb.getnb();
for (int i=0; i<n; i++){
LANG_STRING *t = tb.getitem(i);
if (t->lang == lang){
tb.remove_del (t);
break;
}
}
}
/*
Get the message for a given language
Return NULL if not available.
*/
PUBLIC const char *TR_STRING::getmsg (char lang)
{
const char *ret = NULL;
LANG_STRING *t = gettranslation (lang);
if (t != NULL) ret = t->str.get();
return ret;
}
PUBLIC void TR_STRING::write (FILE *fout)
{
if (!comment.is_empty()){
fputs (comment.get(),fout);
}
fprintf (fout,"!%s\n",id.get());
int n = tb.getnb();
for (int i=0; i<n; i++){
LANG_STRING *t = tb.getitem(i);
fprintf (fout," :%c %s\n",t->lang,t->str.get());
}
}
/*
Record the string (file name) where the message was defined.
*/
PUBLIC void TR_STRING::setorigin(const char *str)
{
origin.setfrom (str);
}
/*
Return the string (generally a file name) telling where the
message was defined.
*/
PUBLIC const char *TR_STRING::getorigin()
{
return origin.get();
}
PUBLIC TR_STRINGS::TR_STRINGS()
{
version = 0;
}
PUBLIC TR_STRING *TR_STRINGS::getitem(int no)
{
return (TR_STRING*)ARRAY::getitem(no);
}
/*
Find a translation unit with a given ID
Return NULL if not found.
*/
PUBLIC TR_STRING *TR_STRINGS::getitem(const char *id)
{
TR_STRING *ret = NULL;
int n = getnb();
for (int i=0; i<n; i++){
TR_STRING *t = getitem(i);
if (strcmp(t->getid(),id)==0){
ret = t;
break;
}
}
return ret;
}
/*
Read a string dictionary
Return -1 if there was any errors
*/
PUBLIC int TR_STRINGS::read (const char *fname)
{
FILE *fin = vfopen (fname,"r");
int err = 0;
if (fin != NULL){
char buf[1000];
/* #Specification: string dictionary / format
The reference dictionary for the translation
system is an ASCII file. This file
contain one record for each string resource.
Each record spans multiple line with the
following format.
Note that this is not the file used by
the running program. A binary file is produced
for each supported language.
So here it is:
#
# comments
# ...
@version 0
!id
:lang string ...
+...
:lang string ...
#
"lang" is a single letter. "string" follows
"lang".
The string may continue over several line. A line
starting with a '+" is a continuation line. Everything
after is the string, including white spaces.
Empty lines are ignored.
*/
TR_STRING *cur = NULL;
SSTRING *curmsg = NULL;
int noline = 0;
SSTRING comment;
while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
noline++;
char *pt = str_skip (buf);
/* #Specification: dictionary file / comments
msgscan is trying to preserve empty
lines and comments between translation units.
Not much inside translation units
*/
if (pt[0] == '#' || pt[0] == '\0'){
comment.append (buf);
}else{
strip_end (buf);
if (pt[0] == '@'){
// Special commands
pt = str_skip (pt+1);
if (strncmp(pt,"version",7)==0
&& isspace(pt[7])){
pt = str_skip(pt+7);
version = atoi(pt);
}else{
fprintf (stderr,"Invalid line %d: %s\n"
,noline,buf);
err++;
}
}else if (pt[0] == '!'){
cur = new TR_STRING (str_skip(pt+1));
add (cur);
cur->add2comment(comment.get());
comment.setfrom ("");
}else if (pt[0] == ':'){
curmsg = cur->settranslation (pt[1]
,str_skip(pt+2));
}else if (pt[0] == '+'){
curmsg->append (pt+1);
}else if (buf[0] != '\0'){
fprintf (stderr,"Invalid line %d: %s\n"
,noline,pt);
err++;
}
}
}
fclose (fin);
int n = getnb();
for (int i=0; i<n; i++){
TR_STRING *t = getitem(i);
t->reset_changed();
}
rstmodified();
}
return err ? -1 : 0;
}
/*
Write back the ASCII dictionary
Return -1 if any error.
*/
PUBLIC int TR_STRINGS::write (const char *fname)
{
int ret = -1;
FILE *fout = vfopen (fname,"w");
if (fout != NULL){
fprintf (fout,"@version %d\n",version);
int n = getnb();
for (int i=0; i<n; i++){
TR_STRING *t = getitem(i);
t->write (fout);
}
ret = fclose (fout);
}
return ret;
}
/*
Write back the ASCII dictionary, modified entry first
Return -1 if any error.
*/
PUBLIC int TR_STRINGS::write_mod (const char *fname)
{
int ret = -1;
FILE *fout = vfopen (fname,"w");
if (fout != NULL){
fprintf (fout,"@version %d\n",version);
int n = getnb();
int i;
for (i=0; i<n; i++){
TR_STRING *t = getitem(i);
if (t->was_modified()) t->write (fout);
}
for (i=0; i<n; i++){
TR_STRING *t = getitem(i);
if (!t->was_modified()) t->write (fout);
}
ret = fclose (fout);
}
return ret;
}
/*
Write the header file
*/
PUBLIC int TR_STRINGS::writeh(const char *sysname, const char *fname)
{
int ret = -1;
FILE *fout = vfopen (fname,"w");
if (fout != NULL){
fprintf (fout,"extern const char **_dictionary_%s;\n"
,sysname);
fprintf (fout,"#ifndef DICTIONARY_REQUEST\n");
fprintf (fout,"\t#define DICTIONARY_REQUEST \\\n"
"\tconst char **_dictionary_%s;\\\n"
"\tTRANSLATE_SYSTEM_REQ _dictionary_req_%s(\"%s\",_dictionary_%s,%d,%d);\\\n"
"\tvoid dummy_dict_%s(){}\n"
,sysname,sysname,sysname,sysname,getnb(),version,sysname);
fprintf (fout,"#endif\n");
fprintf (fout,"#ifndef MSG_U\n");
fprintf (fout,"\t#define MSG_U(id,m)\tid\n");
fprintf (fout,"\t#define MSG_B(id,m,n)\tid\n");
fprintf (fout,"\t#define MSG_R(id)\tid\n");
fprintf (fout,"#endif\n");
int n = getnb();
for (int i=0; i<n; i++){
TR_STRING *t = getitem(i);
fprintf (fout,"#define %s\t_dictionary_%s[%d]\n"
,t->getid(),sysname,i);
}
ret = fclose (fout);
}
return ret;
}
/*
Record a version number only if it is higher than the current one.
*/
PUBLIC void TR_STRINGS::setversion (int ver)
{
if (ver > version) version = ver;
}
/*
Return the version number of this dictionary.
*/
PUBLIC int TR_STRINGS::getversion ()
{
return version;
}
/*
Remove one translation for all messages.
*/
PUBLIC void TR_STRINGS::deltranslation (char lang)
{
int n = getnb();
for (int i=0; i<n; i++){
TR_STRING *t = getitem(i);
t->deltranslation (lang);
}
}
/*
Show all obsolete message.
*/
PUBLIC void TR_STRINGS::showold (char deflang)
{
int n = getnb();
for (int i=0; i<n; i++){
TR_STRING *t = getitem(i);
LANG_STRING *l = t->gettranslation (deflang);
if (l == NULL){
fprintf (stderr,"Obsolete message: %s\n",t->getid());
}
}
}